<?php

namespace api\components\dataCenter;

use api\modules\app\models\MetaArea;
use api\utils\StringUtil;
use app\components\dataCenter\constants\DataField;

trait QueryTrait
{
    public function getSupportFilter()
    {
        return [
            'optTime' => [
                'text' => '操作时间', 'type' => 'dateRange',
                'formatKey' => function ($params) {
                    return 'timestamp_' . $params['optType'];
                }
            ],
            'code' => ['key' => 'args.code', 'text' => '案件编号', 'type' => 'string', 'matchType' => 'fuzzy'],
            'description' => ['key' => 'args.description', 'text' => '案件描述', 'type' => 'string', 'matchType' => 'fuzzy'],
            'opter' => ['key' => 'args.executeUser_*', 'text' => '操作人', 'type' => 'string', 'matchType' => 'fuzzy'],
            // 'infoTypeName' => ['text' => '案件分类', 'type' => 'string', 'matchType' => 'precise'],
            'eventType1' => ['key' => 'args.district_eventType1', 'text' => '案件分类', 'type' => 'string', 'matchType' => 'precise'],
            'eventType2' => ['key' => 'args.district_eventType2', 'text' => '案件分类', 'type' => 'string', 'matchType' => 'precise'],
            'eventType3' => ['key' => 'args.district_eventType3', 'text' => '案件分类', 'type' => 'string', 'matchType' => 'precise'],
            'eventType4' => ['key' => 'args.district_eventType4', 'text' => '案件分类', 'type' => 'string', 'matchType' => 'precise'],
            'eventName' => ['key' => 'args.eventName', 'text' => '案件名称', 'type' => 'string', 'matchType' => 'precise'],
            'source' => [
                'key' => 'event_source', 'text' => '案件来源', 'type' => 'integer', 'matchType' => 'precise',
                'formatValue' => function ($value) {
                    // id => name
                    return $value;
                }
            ],
            'submitType' => ['key' => 'type', 'text' => '上报方式', 'type' => 'string', 'matchType' => 'precise'],
            'discoverType' => ['key' => 'eventDiscoverType', 'text' => '发现方式', 'type' => 'string', 'matchType' => 'precise'],
            'meta_level1' => ['key' => 'province.rawIdentity', 'text' => '所属省', 'type' => 'string', 'matchType' => 'precise'],
            'meta_level2' => ['key' => 'city.rawIdentity', 'text' => '所属市', 'type' => 'string', 'matchType' => 'precise'],
            'meta_level3' => ['key' => 'area_district.rawIdentity', 'text' => '所属区', 'type' => 'string', 'matchType' => 'precise'],
            'meta_level4' => ['key' => 'town.rawIdentity', 'text' => '所属街道', 'type' => 'string', 'matchType' => 'precise'],
            'meta_level5' => ['key' => 'communityCode', 'text' => '所属居村委', 'type' => 'string', 'matchType' => 'precise'],
            'address' => [
                'key' => 'data.address', 'text' => '发生地址', 'type' => 'text', 'matchType' => 'fuzzy'
            ],
            'status' => ['key' => 'args.curStatusCode', 'text' => '案件状态', 'type' => 'string', 'matchType' => 'precise'],
            'gridCode' => ['key' => 'gridCode', 'text' => '网格编号', 'type' => 'string', 'matchType' => 'precise'],
            'period' => ['key' => 'args.curPeriodCode', 'text' => '案件阶段', 'type' => 'string', 'matchType' => 'precise'],
            'opt_meta_level1' => [
                'text' => '操作平台', 'type' => 'string', 'matchType' => 'precise',
                'formatter' => function ($value) {
                    return SearchFilterBuilder::formatOptSearch('args.userMetaLevel1Code_', $value);
                }
            ],
            'opt_meta_level2' => [
                'text' => '操作平台', 'type' => 'string', 'matchType' => 'precise',
                'formatter' => function ($value) {
                    return SearchFilterBuilder::formatOptSearch('args.userMetaLevel2Code_', $value);
                }
            ],
            'opt_meta_level3' => [
                'text' => '操作平台', 'type' => 'string', 'matchType' => 'precise',
                'formatter' => function ($value) {
                    return SearchFilterBuilder::formatOptSearch('args.userMetaLevel3Code_', $value);
                }
            ],
            'opt_meta_level4' => [
                'text' => '操作平台', 'type' => 'string', 'matchType' => 'precise',
                'formatter' => function ($value) {
                    return SearchFilterBuilder::formatOptSearch('args.userMetaLevel4Code_', $value);
                }
            ],
            'opt_meta_level5' => [
                'text' => '操作平台', 'type' => 'string', 'matchType' => 'precise',
                'formatter' => function ($value) {
                    return SearchFilterBuilder::formatOptSearch('args.userMetaLevel5Code_', $value);
                }
            ],
            'optDepartment' => [
                'text' => '操作部门', 'type' => 'integer', 'matchType' => 'precise',
                'formatter' => function ($value) {
                    return SearchFilterBuilder::formatOptSearch('args.userDepCode_', $value);
                }
            ],
            'handleUsers' => [
                // 上报人/受理人/立案人/核查人/结案人
                'text' => '操作+人', 'type' => 'string', 'matchType' => 'fuzzy',
                'formatter' => function ($value) {
                    return SearchFilterBuilder::formatOptSearch('args.executeUser_', $value);
                }
            ],
        ];
    }

    public function formatCondition($query, $params)
    {
        $supportKeys = $this->getSupportFilter();
        foreach ($params as $key => $value) {
            $keyConfig = $supportKeys[$key] ?? [];
            if (empty($keyConfig)) {
                // LogUtil::warn(['message' => '未配置的查询条件', 'key' => $key, 'value' => $value]);
                continue;
            }

            if (isset($keyConfig['formatter'])) {
                $conditions = $keyConfig['formatter']($value);
                foreach ($conditions as $condition) {
                    $query->andFilterWhere($condition);
                }
                continue;
            }

            $formattedKey = $key;
            if (isset($keyConfig['key'])) {
                $formattedKey = $keyConfig['key'];
            }
            if (isset($keyConfig['formatKey'])) {
                $formattedKey = $keyConfig['formatKey']($params);
            }
            $formattedValue = $value;
            if (isset($keyConfig['formatValue'])) {
                $formattedValue = $keyConfig['formatValue']($value);
            }
            if ($keyConfig['type'] == 'dateRange') {
                $query->andFilterWhere([SearchFilterBuilder::OPERATOR_TIME_RANGE, $formattedKey, $formattedValue]);
                continue;
            }

            if ($keyConfig['type'] == 'string' && $keyConfig['matchType'] == 'fuzzy') {
                $query->andFilterWhere([
                    SearchFilterBuilder::OPERATOR_QUERY_STRING, $formattedKey,
                    StringUtil::isEmpty($formattedValue) ? null : '*' . $formattedValue . '*'
                ]);
                continue;
            }

            if ($keyConfig['type'] == 'text') {
                $query->andFilterWhere([
                    SearchFilterBuilder::OPERATOR_MATCH_PHRASE_PREFIX, $formattedKey, $formattedValue
                ]);
                continue;
            }

            $query->andFilterWhere([$formattedKey => $formattedValue]);
        }
    }

    /**
     * @todo 暂时没用
     */
    public function genRoleCondition($query, $user)
    {
        return $query;
        $roleCondition = $user;
        // 处理情况
        if (!empty($roleCondition['department'])) {
            $department = MetaArea::findOne(['id' => $roleCondition['department']]);
            $level = $department->getLevel();
        } elseif (!empty($roleCondition['street'])) {
            $level = 't';
        } else {
            $level = 'd';
        }
        $fieldParams['handle_status'] = "args.handle_status_${level}";
        $query->andFilterWhere(["args.handle_status_${level}" => $params['handle_status'] ?? null]);

        //若用户有部门 说明用户为部门级别 则查此部门相关的数据，否则查区街道相关数据
        if (!empty($roleCondition['department'])) {
            $query->andWhere([
                SearchFilterBuilder::OPERATOR_QUERY_STRING,
                'args.chs_dealDepartmentId,args.executeDepId_*',
                implode(' OR ', $roleCondition['department'])
            ]);
        } else {
            //区
            $query->andFilterWhere(['area_district.rawIdentity' => array_map(
                function ($value) {
                    return $this->getAreaCode($value);
                },
                $roleCondition['district']
            )]);
            //街道
            $query->andFilterWhere([
                SearchFilterBuilder::OPERATOR_QUERY_STRING,
                'args.chs_dealStreetCode,args.chs_user_street_code*',
                array_map(
                    function ($value) {
                        return $this->getAreaCode($value);
                    },
                    $roleCondition['street']
                )
            ]);
        }

        return $query;
    }

    private function getAreaCode($id)
    {
        if (StringUtil::isEmpty($id)) return null;

        $cache_namespace = $this->getCachePrefix() . 'areacode:';
        $ttl_key = $cache_namespace . 'ttl';
        $key = $cache_namespace . $id;
        $result = $this->redis->get($key);
        if (!$result || !$this->redis->get($ttl_key)) {
            $area = MetaArea::find()->where(['status' => 1])
                                    ->get(['id', 'name'])
                                    ->all();
            $data = [];
            foreach ($area as $item) {
                $data[$cache_namespace . $item['id']] = $item['code'];
            }
            $this->setCache($cache_namespace, $data);
            $result = $data[$key] ?? null;
        }
        return $result;
    }

    private function getCommunity($code)
    {
        if (StringUtil::isEmpty($code)) return null;

        $cache_namespace = $this->getCachePrefix() . 'community:';
        $ttl_key = $cache_namespace . 'ttl';
        $key = $cache_namespace . $code;
        $result = $this->redis->get($key);
        if (!$result || !$this->redis->get($ttl_key)) {
            // $community = Query::table('dict_community')
            //     ->where('status', 1, '=')
            //     ->get(['id', 'code'])->getResult();
            $community = [];
            $data = [];
            foreach ($community as $item) {
                $data[$cache_namespace . $item['id']] = $item['code'];
            }
            $this->setCache($cache_namespace, $data);
            $result = $data[$key] ?? null;
        }
        return $result;
    }
}
